package com.sites.common;

import java.sql.Connection;

import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.wall.WallFilter;
import com.jfinal.aop.Aop;
import com.jfinal.config.Constants;
import com.jfinal.config.Handlers;
import com.jfinal.config.Interceptors;
import com.jfinal.config.JFinalConfig;
import com.jfinal.config.Plugins;
import com.jfinal.config.Routes;
import com.jfinal.ext.handler.ContextPathHandler;
import com.jfinal.ext.interceptor.SessionInViewInterceptor;
import com.jfinal.kit.Prop;
import com.jfinal.kit.PropKit;
import com.jfinal.plugin.activerecord.ActiveRecordPlugin;
import com.jfinal.plugin.druid.DruidPlugin;
import com.jfinal.plugin.ehcache.EhCachePlugin;
import com.jfinal.template.Engine;
import com.sites.cds.common.directive.ArticleFilesListDirective;
import com.sites.cds.common.directive.ColumnArticleListDirective;
import com.sites.cds.common.directive.ColumnListDirective;
import com.sites.cds.common.directive.CutStringDirective;
import com.sites.cds.common.directive.HotNewsDirective;
import com.sites.cds.common.directive.LatestNewsDirective;
import com.sites.cds.config.CdsRoutes;
import com.sites.cms.common.StatusDirective;
import com.sites.cms.config.CMSRoutes;
import com.sites.cms.permission.PermissionElementDirective;
import com.sites.cms.permission.PermissionListDirective;
import com.sites.cms.site.SiteService;
import com.sites.common.file.FileController;
import com.sites.common.model._MappingKit;

/**
 * 工程主配置文件
 * 
 * @author zyg
 * 2020年1月2日 下午10:13:18
 */
public class CmsConfig extends JFinalConfig {
	
	/*
	 * 使用 jfinal-undertow 时此处仅保留声明，不能有加载代码
	 * (社区直播视频里有介绍)当使用下面的方法启动项目时，如果类里有static块或者引用，当类被加载的时候会被执行，导致资源找不到
	 */
	private static Prop p;
	private WallFilter wallFilter;

	
	/**
	 * 加载主配置文件
	 */
	static void loadConfig() {
		if (p == null) {
			p = PropKit.use("cmsConfig.txt");
			// 如果存在生产版本的配置文件则追加，更好地区分开发环境和生产环境
			p.appendIfExists("cmsConfig-pro.txt");
		}
	}
	
	@Override
	public void configConstant(Constants me) {
		loadConfig();
		me.setDevMode(p.getBoolean("devMode", false));
		me.setError404View("/cds/_common/404.html");
		me.setError500View("/cds/_common/500.html");
		
		// 支持 Controller、Interceptor、Validator 之中使用 @Inject 注入业务层，并且自动实现 AOP
		me.setInjectDependency(true);
	}

	@Override
	public void configRoute(Routes me) {
		me.add(new CdsRoutes());
		me.add(new CMSRoutes());
		me.add("/file", FileController.class);
	}

	@Override
	public void configEngine(Engine me) {
		me.setDevMode(p.getBoolean("engineDevMode"));
		me.addSharedObject("site", new SiteInfo());
		//添加自定义指令，要放在公用模板前面，不然在公用模板里会报错指令找不到
		me.addDirective("ped", PermissionElementDirective.class);
		me.addDirective("pld", PermissionListDirective.class);
		me.addDirective("status", StatusDirective.class);
		me.addDirective("cald", ColumnArticleListDirective.class);
		me.addDirective("cld", ColumnListDirective.class);
		me.addDirective("news", LatestNewsDirective.class);
		me.addDirective("hotNews", HotNewsDirective.class);
		me.addDirective("cutStr", CutStringDirective.class);
		me.addDirective("afld", ArticleFilesListDirective.class);
		//添加公用模板
		me.addSharedFunction("/cms/common/cmsLayout.html");
		me.addSharedFunction("/cms/common/paginate.html");
	}

	@Override
	public void configPlugin(Plugins me) {
		DruidPlugin druidPlugin = getDruidPlugin();
		wallFilter = new WallFilter();			// 加强数据库安全
		wallFilter.setDbType("mysql");
		druidPlugin.addFilter(wallFilter);
		druidPlugin.addFilter(new StatFilter());	// 添加 StatFilter 才会有统计数据
		me.add(druidPlugin);
		
		ActiveRecordPlugin arp = new ActiveRecordPlugin(druidPlugin);
		arp.setTransactionLevel(Connection.TRANSACTION_READ_COMMITTED);
		_MappingKit.mapping(arp);
		me.add(arp);
		arp.setShowSql(p.getBoolean("devMode", false));
		
		arp.getEngine().setToClassPathSourceFactory();
		arp.addSqlTemplate("/sql/all.sql");
		
		me.add(new EhCachePlugin());//启用缓存插件
	}
	
	/**
	 * 抽取成独立的方法，便于 _Generator 中重用该方法，减少代码冗余
	 */
	public static DruidPlugin getDruidPlugin() {
		loadConfig();
		String jdbcUrl = p.get("jdbcUrl").trim();
		String user = p.get("user").trim();
		String password = p.get("password").trim();
		String driverClass = p.get("driverClass").trim();
		
		DruidPlugin druidPlugin = new DruidPlugin(
				jdbcUrl,
				user, 
				password,
				driverClass, 
				"config");//config是固定的，这个是JFinal要求的，有这个标记才会进行数据库密码的加解密
		druidPlugin.setPublicKey(p.get("publicKey").trim());
		
		return druidPlugin;
	}

	/**
	 * 配置全局拦截器
	 */
	@Override
	public void configInterceptor(Interceptors me) {
		/*
		 * 配置session过滤，JFinal默认是不支持session传递数据的，配置后才能在页面获取session中存放的数据
		 * 有这个配置后还可以在自定义指令中通过scope.get("session")获取session
		 */
		me.add(new SessionInViewInterceptor());
	}

	@Override
	public void configHandler(Handlers me) {
		me.add(new ContextPathHandler("ctx"));//这个是设置上下文路径的
	}
	
	/**
	 * jfinal启动后执行的方法，在这里执行一些项目初始化的操作
	 */
	@Override
	public void  onStart() {
		System.out.println("当前版本："+SiteInfo.version);
		System.out.println("当前版本更新时间："+SiteInfo.updateDate);
		// 初始化主站点信息
		Aop.get(SiteService.class).initSiteInfo();
	}

}
